/**
 * @Date: Apr 5, 2010 12:37:09 PM
 */
package com.philip.journal.home.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import com.philip.journal.common.BeanUtils;
import com.philip.journal.common.StringUtils;
import com.philip.journal.core.Constant;
import com.philip.journal.core.Messages.Error;
import com.philip.journal.core.bean.User;
import com.philip.journal.core.service.BaseService;
import com.philip.journal.core.service.ServiceFacade;
import com.philip.journal.home.bean.Branch;
import com.philip.journal.home.bean.Category;
import com.philip.journal.home.bean.Entry;
import com.philip.journal.home.dao.BranchDAO;
import com.philip.journal.home.dao.EntryDAO;

/**
 * @author cry30
 */
public class EntryServiceImpl extends BaseService implements EntryService {

    @Override
    public List<Category> getCategories(final Map<String, Object> session) {
        final List<Branch> allBranch = getDaoFacade().getBranchDAO().readAll();
        final List<Category> retval = new ArrayList<Category>();

        Collections.sort(allBranch, new Comparator<Branch>() {
            @Override
            public int compare(final Branch branch1, final Branch branch2) {
                return Long.valueOf(branch1.getBranchId()).compareTo(branch2.getBranchId());
            }
        });

        for (final Branch nextBranch : allBranch) {
            if (nextBranch.getBranchId() != 0) {
                final StringBuilder categoryDesc = new StringBuilder(nextBranch.getName()); // NOPMD by r39 on 3/30/11 2:52 PM

                Branch branch = nextBranch;

                while (branch.getParent() != null && branch.getParent().getBranchId() != 0) { // NOPMD by r39
                    categoryDesc.insert(0, branch.getParent().getName() + " > ");
                    branch = branch.getParent();
                }
                retval.add(new Category(nextBranch.getBranchId(), categoryDesc.toString())); // NOPMD by r39
            }
        }
        return retval;
    }

    @Override
    public long saveEntry(final Map<String, Object> session, final long branchId, final long entryId,
            final String title, final String description)
    {
        if (title == null || description == null) {
            throw new IllegalArgumentException(Error.IAE_NULL);
        }
        final Branch branch = getDaoFacade().getBranchDAO().read(branchId);
        if (branch == null) {
            throw new IllegalArgumentException("Branch ID: " + branchId + " was not found in the datasource.");
        }
        Entry entry = getDaoFacade().getEntryDAO().read(entryId);
        if (entry == null) {
            entry = new Entry(title, description, branch);
            entry.setCreator((User) session.get(Constant.CURRENT_USER));
        } else {
            entry.setUpdater((User) session.get(Constant.CURRENT_USER));
            entry.setBranch(branch);
        }

        entry.setDescription(description);
        entry.setTitle(title);
        getDaoFacade().getEntryDAO().save(entry);
        return entry.getNodeId();
    }

    @Override
    public List<Entry> getEntries(final Map<String, Object> session, final long branchId) {
        return getDaoFacade().getEntryDAO().readAllByBranch(branchId);
    }

    @Override
    public void deleteEntry(final Map<String, Object> session, final long entryId)
    {
        getDaoFacade().getEntryDAO().delete(entryId);
    }

    @Override
    public Entry getEntryDetail(final Map<String, Object> session, final long entryId) {
        return getDaoFacade().getEntryDAO().read(entryId);
    }

    @Override
    public void moveEntry(final Map<String, Object> session, final long newParentId, final long entryId)
    {
        final EntryDAO entryDao = getDaoFacade().getEntryDAO();
        final BranchDAO branchDao = getDaoFacade().getBranchDAO();

        final Entry entry = entryDao.read(entryId);
        final Branch parent = branchDao.read(newParentId);
        if (entry == null || parent == null) {
            throw new IllegalArgumentException(Error.IAE_GENERIC);
        } else {
            entry.setBranch(parent);
            entryDao.save(entry);
        }
    }

    @Override
    public void renameEntry(final Map<String, Object> session, final long entryId, final String newTitle)
    {
        if (newTitle == null || "".equals(newTitle)) {
            throw new IllegalArgumentException(Error.IAE_NULLOREMPTY);
        } else {
            final EntryDAO entryDao = getDaoFacade().getEntryDAO();
            final Entry entry = entryDao.read(entryId);
            if (entry == null) {
                throw new IllegalArgumentException("Entry ID: " + entryId + " was not found.");
            } else {
                entry.setTitle(newTitle);
                entryDao.save(entry);
            }
        }
    }

    @Override
    public List<Entry> searchEntriesSimple(final Map<String, Object> session, final String searchParam)
    {

        if (searchParam == null || searchParam.length() < MIN_SEARCH_LENGTH) {
            throw new IllegalArgumentException(Error.IAE_GENERIC);
        } else {
            Map<String, String> criteria = new HashMap<String, String>();
            criteria.put("description", "%" + searchParam + "%");
            final List<Entry> matchedDescList = getDaoFacade().getEntryDAO().searchIlike(criteria);

            criteria = new HashMap<String, String>();
            criteria.put("title", "%" + searchParam + "%");
            final List<Entry> matchedList = getDaoFacade().getEntryDAO().searchIlike(criteria);

            for (final Entry entry : matchedDescList) {
                if (!matchedList.contains(entry)) {

                    final String htmlFreeText = getStringUtils().removeHtmlTags(entry.getDescription());
                    if (htmlFreeText.toLowerCase(Locale.getDefault()).indexOf(
                            searchParam.toLowerCase(Locale.getDefault())) > -1) {
                        matchedList.add(entry);
                    }
                }
            }

            final ServiceFacade facd = getFacade(session);
            for (final Entry entry : matchedList) {
                entry.setTreePath(facd.getEntryTreePath(session, entry));
            }

            return matchedList;
        }
    }

    @Override
    public List<Entry> searchEntriesSimple(final Map<String, Object> session, final String searchParam,
            final String sortField, final String direction)
    {
        final ServiceFacade facade = (ServiceFacade) session.get(Constant.SERVICE_FACADE);

        final List<Entry> list = facade.searchEntriesSimple(session, searchParam);

        final Comparator<Entry> comparator = new Comparator<Entry>() {
            @SuppressWarnings("unchecked")
            @Override
            public int compare(final Entry entry1, final Entry entry2) {
                final Comparable<Object> object1 = (Comparable<Object>) BeanUtils.getProperty(entry1, sortField);
                final Comparable<Object> object2 = (Comparable<Object>) BeanUtils.getProperty(entry2, sortField);
                return object1.compareTo(object2);
            }
        };

        Collections.sort(list, comparator);
        if (Constant.SortOrder.DESC.equals(direction)) {
            Collections.reverse(list);
        }

        return list;
    }

    StringUtils getStringUtils() {
        return StringUtils.getInstance();
    }

}

